﻿using PersistenceLayer.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PersistenceLayer.DAL
{
	public class ProdutoDAL
	{
		public enum Ordenacao
		{
			Newest = 1,
			Name,
			Cheaper,
			Expensive
		}

		private Entities Entity;
		public ProdutoDAL()
		{
			Entity = new Entities();
		}

		public Int64 Adicionar(Produto p)
		{
			Entity.Produto.Add(p);
			Entity.SaveChanges();
			return p.ID;
		}
		public Produto Obter(Int64 pID)
		{
			return Entity.Produto.Where(a => a.ID == pID).SingleOrDefault();
		}
		public List<Produto> Listar()
		{
			return Entity.Produto.ToList();
		}
		public List<Produto> Listar(int _skip, int _take, int _ord, string _filtro, bool listarSemEspecificacao, out int _numProdutos)
		{
			try
			{
				_numProdutos = 0;
				List<Produto> lp = new List<Produto>();

				if (_filtro.Equals(string.Empty))
				{
					if (listarSemEspecificacao)
						lp = Entity.Produto.Where(a => a.Peso != 0).ToList();
					else
					{
						foreach (var p in Entity.Produto.Where(a => a.Peso != 0).ToList())
						{
							bool ok = false;
							if (p.Produto_Especificacao.Count > 0)
								foreach (var pe in p.Produto_Especificacao.ToList())
								{
									if (pe.Quantidade > 0)
										ok = true;
								}

							if (ok)
								lp.Add(p);
						}
					}
				}
				else
				{
					var lm = Entity.Produto_Marca.Where(a => a.Descricao.Contains(_filtro)).ToList();
					var lc = Entity.Produto_Categoria.Where(a => a.Descricao.Contains(_filtro) || a.Tags.Contains(_filtro)).ToList();

					if (listarSemEspecificacao)
					{
						lm.ForEach(a => lp.AddRange(Entity.Produto.Where(b => b.Marca_ID == a.ID && b.Peso != 0).ToList()));
						lc.ForEach(a => lp.AddRange(Entity.Produto.Where(b => b.Categoria_ID == a.ID && b.Peso != 0).ToList()));
					}
					else
					{
						foreach (var m in lm)
						{
							var lpm = Entity.Produto.Where(a => a.Marca_ID == m.ID && a.Peso != 0).ToList();

							foreach (var p in lpm)
							{
								bool ok = false;
								if (p.Produto_Especificacao.Count > 0)
									foreach (var pe in p.Produto_Especificacao.ToList())
									{
										if (pe.Quantidade > 0)
											ok = true;
									}

								if (ok)
									lp.Add(p);
							}
						}

						foreach (var c in lc)
						{
							var lpc = Entity.Produto.Where(a => a.Categoria_ID == c.ID && a.Peso != 0).ToList();

							foreach (var p in lpc)
							{
								bool ok = false;
								if (p.Produto_Especificacao.Count > 0)
									foreach (var pe in p.Produto_Especificacao.ToList())
									{
										if (pe.Quantidade > 0)
											ok = true;
									}

								if (ok)
									lp.Add(p);
							}
						}
					}
				}

				_numProdutos = lp.Count;

				switch (_ord)
				{
					case 1:
						return lp.OrderBy(a => a.Data).Skip(_skip).Take(_take).ToList();
					case 2:
						return lp.OrderBy(a => a.Modelo).Skip(_skip).Take(_take).ToList();
					case 3:
						return lp.OrderBy(a => a.Preco).Skip(_skip).Take(_take).ToList();
					case 4:
						return lp.OrderByDescending(a => a.Preco).Skip(_skip).Take(_take).ToList();
					default:
						return lp;
				}
			}
			catch (Exception)
			{
				throw;
			}
		}
		public List<Produto> ListarPorCodigo(int _skip, int _take, int _ordenacao, string _filtro, out int _numProdutos)
		{
			try
			{
				List<Produto> lp = new List<Produto>();
				_numProdutos = 0;

				if (_filtro.Equals(string.Empty))
					lp = Entity.Produto.ToList();
				else
				{
					var le = Entity.Produto_Especificacao.Where(a => a.CodigoLoja.Contains(_filtro)).ToList();
					le.ForEach(b => lp.AddRange(Entity.Produto.Where(c => c.ID == b.Produto_ID).ToList()));
				}

				_numProdutos = lp.Count;

				switch (_ordenacao)
				{
					case 1:
						return lp.OrderBy(a => a.Data).Skip(_skip).Take(_take).ToList();
					case 2:
						return lp.OrderBy(a => a.Modelo).Skip(_skip).Take(_take).ToList();
					case 3:
						return lp.OrderBy(a => a.Preco).Skip(_skip).Take(_take).ToList();
					case 4:
						return lp.OrderByDescending(a => a.Preco).Skip(_skip).Take(_take).ToList();
					default:
						return lp;
				}
			}
			catch (Exception)
			{
				throw;
			}
		}
		public List<Produto> ListarPorMaster(int _skip, int _take, int _ordenacao, string _filtro, out int _numProdutos)
		{
			try
			{
				List<Produto> lp = new List<Produto>();
				_numProdutos = 0;

				if (_filtro.Equals(string.Empty))
					lp = Entity.Produto.ToList();
				else
				{
					var lcm = Entity.Produto_Categoria_Master.Where(a => a.Descricao.Contains(_filtro)).ToList();

					lcm.ForEach(a => lp.AddRange(Entity.Produto.Where(b => b.CategoriaMaster_ID == a.ID).ToList()));

				}

				_numProdutos = lp.Count;

				switch (_ordenacao)
				{
					case 1:
						return lp.OrderBy(a => a.Data).Skip(_skip).Take(_take).ToList();
					case 2:
						return lp.OrderBy(a => a.Modelo).Skip(_skip).Take(_take).ToList();
					case 3:
						return lp.OrderBy(a => a.Preco).Skip(_skip).Take(_take).ToList();
					case 4:
						return lp.OrderByDescending(a => a.Preco).Skip(_skip).Take(_take).ToList();
					default:
						return lp;
				}
			}
			catch (Exception)
			{
				throw;
			}
		}
		public void Atualizar(Produto novo)
		{
			var old = Entity.Produto.Where(a => a.ID == novo.ID).Single();
			Entity.Entry(old).CurrentValues.SetValues(novo);
			Entity.SaveChanges();
		}
		public bool Existe(Produto p)
		{
			try
			{
				return Entity.Produto.Count(a => a.Categoria_ID == p.Categoria_ID && a.Marca_ID == p.Marca_ID && a.Modelo == p.Modelo) > 0;
			}
			catch (Exception)
			{
				throw;
			}
		}
		public bool Destacado(Produto p)
		{
			var d = Entity.Produto_Destaque.Where(a => a.Produto_ID == p.ID).SingleOrDefault();

			return ((d != null) || (d.ID > 0));
		}
	}
}